/**
 * \brief Function return type dependent on class trait.
 *
 * \author Bartosz Kedra (bartosz.kedra@gmail.com)
 */
#include <assert.h>

template<typename T> struct return_type_traits
{
   typedef long ret;
};

template <> struct return_type_traits<char>
{
   typedef short ret;
};

template <> struct return_type_traits<short>
{
   typedef int ret;
};

template<typename T> typename return_type_traits<T>::ret sum(const T *first, const T *last)
{
   typename return_type_traits<T>::ret return_val = 0;

   for ( ; first != last; first++)
   {
      return_val += *first;
   }
   return return_val;
}

int main()
{
   const char char_tab[] = { 0x10, 0x20, 0x30, 0x40};
   const int char_tab_el_nr = sizeof(char_tab) / sizeof(char_tab[0]);

   const short short_tab[] = { 0x10, 0x20, 0x30, 0x40};
   const int short_tab_el_nr = sizeof(short_tab) / sizeof(short_tab[0]);

   const int int_tab[] = { 0x10, 0x20, 0x30, 0x40};
   const int int_tab_el_nr = sizeof(int_tab) / sizeof(int_tab[0]);

   const long long_tab[] = { 0x10, 0x20, 0x30, 0x40};
   const int long_tab_el_nr = sizeof(long_tab) / sizeof(long_tab[0]);

   assert(sizeof(sum(char_tab, char_tab + char_tab_el_nr)) == sizeof(short));
   assert(sizeof(sum(short_tab, short_tab + short_tab_el_nr)) == sizeof(int));
   assert(sizeof(sum(int_tab, int_tab + int_tab_el_nr)) == sizeof(long));
   assert(sizeof(sum(long_tab, long_tab + long_tab_el_nr)) == sizeof(long));
   return 0;
}
